import React,{ useState,useEffect } from 'react'
import { Table,Button,Modal,Tree } from 'antd'
// 引入 antd 组件图标
import { DeleteOutlined,UnorderedListOutlined,ExclamationCircleOutlined } from '@ant-design/icons'
import axios from 'axios'
// 将confirm确认框从Modal组件中解构出来
const { confirm } = Modal

export default function RoleList() {
  // 存储表格Table组件需要的数据
  const [dataSource,setDataSource] = useState([])

  // 存储树型结构Tree组件需要的数据
  const [rightList,setRightList] = useState([])

  // 存储树形结构Tree组件中默认选中状态的数据
  const [currentRights,setCurrenRights] = useState([])

  // 决定弹出框组件是否显示
  const [isModalVisible,setIsModalVisible] = useState(false)

  // 存储当前点击的表格项元素的id值
  const [currentId,setCurrentId] = useState(0)

  /* 
    useEffect钩子中的第一次参数是一个函数，它会在组件渲染完成后执行，第二个参数用于设置依赖项列表(当依赖项发生变化时，才会重新执行回调函数)
    这里的依赖项列表是一个空数组，所以这个useEffect只会在组件初始化时执行一次
  */
  useEffect(()=>{
    // 请求表格数据
    axios.get('http://localhost:5000/roles').then((res) => {
      setDataSource(res.data)
    })
  },[])

  useEffect(()=>{
    // 请求树形结构组件所需要的数据
    axios.get('http://localhost:5000/rights?_embed=children').then((res) => {
      setRightList(res.data)
    })
  },[])

  // 删除按钮点击后的事件回调
  const confirmMethod = (item)=>{
    // 点击后弹出确认框
    confirm({
      title: '你确定要删除?',
      icon: <ExclamationCircleOutlined />,
      cancelText: "取消",
      onOk() {
        deleteMethod(item)
      },
      onCancel() {

      },
    })
  }

  // 确认框中的确认按钮点击后的事件回调
  const deleteMethod = (item) => {
    // 利用filter方法将dataSource中元素的id属性值等于当前这个表格项元素的id值过滤掉，从而实现在页面上删除这个表格项
    setDataSource(dataSource.filter(data => data.id !== item.id))
    // 上面那种方法删除后再刷新就不会有影响，下面是直接删除服务器中的数据，所以刷新后仍会有影响，所以这里不用下面那种方式
    // axios.delete(`http://localhost:5000/roles/${item.id}`)
  }

  // 弹出框Modal组件的确认按钮点击事件回调
  const handleOk = (item)=>{
    // 隐藏弹出框Modal组件
    setIsModalVisible(false)
    // 点击确认按钮后，树形结构Tree组件的分支元素状态发生了改变，同步dataSource
    setDataSource(dataSource.map(item=>{
      if(item.id === currentId){  // 在dataSource中根据id找到对应的当前被点击的编辑按钮所在的表格项元素
        return {
          // 这里是用 ... 展开运算符将item展开，并且将item元素中的rights属性的值修改为currentRights，最后将这个展开的item放在一个对象中再return返回
          ...item,
          rights:currentRights
        }
      }
      return item
    }))
    // 上面这种方式刷新后无影响，下面这种方法刷新后仍有影响，因为是通过请求修改后端的数据
    axios.patch(`http://localhost:5000/roles/${currentId}`,{  // 通过接口在后端数据库中的role分类下找到id为变量currentId的元素，并且将其中的rights属性值更新为变量currentRights
      rights:currentRights
    })
  }

  // 弹出框Modal组件的取消按钮点击事件回调
  const handleCancel = ()=>{
    // 隐藏弹出框Modal组件
    setIsModalVisible(false)
  }

  // 树形结构Tree组件的分支元素的选中状态发生改变的时候会触发的事件回调
  const onCheck = (checkKeys)=>{
    // console.log(checkKeys);  // checkKeys 接收到的是被选中的分支元素的key属性
    setCurrenRights(checkKeys)
  }

  const columns = [
    {
      title: 'ID',
      dataIndex: 'id',
      // render是给当前这一列中的所有表格都渲染对应的组件标签
      render: (id) => {
        return <b>{id}</b>
      }
    },
    {
      title: '角色名称',
      dataIndex: 'roleName',
    },
    {
      title: '操作',
      // render 是给当前这一列表格项下都渲染指定的组件标签
      render: (item) => {
        return <>
          {/* <Tooltip placement="left" title={text}> */}
            <Button 
              danger 
              type="danger" 
              shape="circle" 
              icon={<DeleteOutlined/>} 
              onClick={() => { confirmMethod(item) }}
              style={{marginRight:"5px"}}
            ></Button>
          {/* </Tooltip> */}

          {/* <Tooltip placement="right" title={text1}> */}
            <Button 
            type="primary" 
            shape="circle" 
            icon={<UnorderedListOutlined/>} 
            onClick={() => {
              // 当前Button组件点击后将isModalVisible值改为true，使得Modal弹出框组件显示
              setIsModalVisible(true)
              // 将当前这个表格项元素的rights赋值给currentRights，也就是设置树形结构Tree组件的默认选中状态的数据
              setCurrenRights(item.rights)
              // 将当前被点击的编辑按钮所在的表格项元素的id值赋值给currentId
              setCurrentId(item.id)
            }}></Button>
          {/* </Tooltip> */}
        </>
      }
    }
  ]

  return (
    <div>
      {/* 表格组件 */}
      {/* 
        columns 表格列的配置描述(每一列的开头的设置)
        dataSource 数据数组，设置每一行具体的信息
        rowKey 指定属性作为当前表格项的key，下面是将表格项元素的id值作为表格项的key
      */}
      <Table 
        dataSource={dataSource} 
        columns={columns}
        // item 是当前表格项元素
        rowKey={(item)=>{return item.id}}
      ></Table>

      {/* 弹出框组件 */}
      {/* 
        title 用于设置组件标题
        open 用于设置当前组件的显示与隐藏，当值为true的时候显示，为false的时候隐藏
        onOk 是当组件的确认按钮被点击后触发的事件
        onCancel 是当组件的取消按钮被点击后触发的事件
      */}
      <Modal 
        title="权限分配" 
        open={isModalVisible} 
        onOk={handleOk} 
        onCancel={handleCancel}
      >

        {/* 树形结构组件 */}
        {/* 
          checkable 设置树形组件下的分支元素能否被选中
          treeData 设置树形组件的分支元素
          defaultCheckedKeys 设置默认为选中状态的分支元素，这会使得Tree组件变成非受控组件
              当 defaultCheckedKeys 的值 currentRights 发生变化的时候，Tree组件不会重新渲染
          checkedKeys 这个作用和 defaultCheckedKeys 一样，区别是 checkedKeys 会使得Tree组件变成受控组件
              Tree变成受控组件就是会收到指定属性的影响，如果指定属性的值发生变化，那么这个Tree组件也会重新渲染
              这里 checkedKeys 的值为 currentRights ，那么当currentRights属性值发生变化的时候，这个组件就会重新渲染
          onCheck 当树形结构组件的分支元素的选中状态发生改变的时候会触发的事件
          checkStrictly 使得树形结构下的分支元素互不影响
        */}
        <Tree
          checkable
          treeData={rightList}
          checkedKeys={currentRights}
          checkStrictly={true}
          fieldNames={{ title: "label" }}
          onCheck={onCheck}
        />
      </Modal>
    </div>
  )
}
